// 使用现代C++特性实现的日期时间库
// 基于值语义设计，提供高效、线程安全的日期时间操作

#ifndef MODERN_DATETIME_H
#define MODERN_DATETIME_H

#include <chrono>
#include <string>
#include <vector>
#include <compare>
#include <ctime>

namespace cytoolkit {

// 日期格式枚举
enum class DateFormat {
    ISODate,    // ISO 8601 格式: YYYY-MM-DD
    RFC2822Date, // RFC 2822 格式
    TextDate     // 文本格式
};

// 星期枚举
enum class DayOfWeek {
    Monday = 1,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

// 日期时间错误类
class DateTimeError : public std::exception {
public:
    enum ErrorCode {
        InvalidDate,
        Overflow,
        ParseError
    };

    explicit DateTimeError(ErrorCode code) : code_(code) {}

    ErrorCode getErrorCode() const { return code_; }
    const char* what() const noexcept override {
        switch (code_) {
            case InvalidDate: return "Invalid date"; break;
            case Overflow: return "Date/time overflow"; break;
            case ParseError: return "Parse error"; break;
            default: return "Unknown error"; break;
        }
    }

private:
    ErrorCode code_;
};

// 日期类
class Date {
public:
    static constexpr int kDaysPerWeek = 7;
    static constexpr int kJulianDayOf1970_01_01 = 2440588;

    // 构造函数
    Date();
    Date(int year, int month, int day);
    Date(int julianDayNum);
    Date(const struct tm& tm);

    // 属性访问
    bool isValid() const { return valid_; }
    int year() const { return year_; }
    int month() const { return month_; }
    int day() const { return day_; }
    int dayOfWeek() const;
    int dayOfYear() const;
    int daysInMonth() const;
    int julianDay() const { return julianDayNumber_; }

    // 修改方法
    Date addDays(int days) const;
    Date addMonths(int months) const;
    Date addYears(int years) const;
    int64_t daysTo(const Date& other) const;

    // 字符串转换
    std::string toString(const std::string& format = "YYYY-MM-DD") const;
    std::string toISOString() const;
    
    // 静态方法
    static Date currentDate();
    static Date fromString(const std::string& str);
    static bool isLeapYear(int year);

    // 比较操作符
    bool operator==(const Date& other) const { return julianDayNumber_ == other.julianDayNumber_; }
    bool operator!=(const Date& other) const { return julianDayNumber_ != other.julianDayNumber_; }
    bool operator<(const Date& other) const { return julianDayNumber_ < other.julianDayNumber_; }
    bool operator<=(const Date& other) const { return julianDayNumber_ <= other.julianDayNumber_; }
    bool operator>(const Date& other) const { return julianDayNumber_ > other.julianDayNumber_; }
    bool operator>=(const Date& other) const { return julianDayNumber_ >= other.julianDayNumber_; }

private:
    // 内部方法
    void updateByJulianDay();
    void updateJulianDay();
    bool isDateValid(int year, int month, int day) const;

    int julianDayNumber_; // 儒略日
    int year_;            // 年
    int month_;           // 月 [1-12]
    int day_;             // 日 [1-31]
    bool valid_;          // 是否有效
};

// 时间类
class Time {
public:
    // 构造函数
    Time();
    Time(int hour, int minute, int second, int msec = 0);
    Time(int msecsSinceMidnight);
    Time(const struct timeval& tv);

    // 属性访问
    bool isValid() const { return valid_; }
    int hour() const { return hour_; }
    int minute() const { return minute_; }
    int second() const { return second_; }
    int msec() const { return msec_; }
    int msecsSinceStartOfDay() const { return msecsSinceMidnight_; }

    // 修改方法
    Time addHours(int hours) const;
    Time addMinutes(int minutes) const;
    Time addSecs(int seconds) const;
    Time addMSecs(int msecs) const;
    int64_t secsTo(const Time& other) const;

    // 字符串转换
    std::string toString(const std::string& format = "HH:MM:SS") const;
    
    // 静态方法
    static Time currentTime();
    static Time fromString(const std::string& str);

    // 比较操作符
    bool operator==(const Time& other) const { return msecsSinceMidnight_ == other.msecsSinceMidnight_; }
    bool operator!=(const Time& other) const { return msecsSinceMidnight_ != other.msecsSinceMidnight_; }
    bool operator<(const Time& other) const { return msecsSinceMidnight_ < other.msecsSinceMidnight_; }
    bool operator<=(const Time& other) const { return msecsSinceMidnight_ <= other.msecsSinceMidnight_; }
    bool operator>(const Time& other) const { return msecsSinceMidnight_ > other.msecsSinceMidnight_; }
    bool operator>=(const Time& other) const { return msecsSinceMidnight_ >= other.msecsSinceMidnight_; }

private:
    // 内部方法
    void updateByMSecs();
    bool isTimeValid(int hour, int minute, int second, int msec) const;

    int msecsSinceMidnight_; // 从午夜开始的毫秒数
    int hour_;              // 时 [0-23]
    int minute_;            // 分 [0-59]
    int second_;            // 秒 [0-59]
    int msec_;              // 毫秒 [0-999]
    bool valid_;            // 是否有效
};

// 时区类
class TimeZone {
public:
    // 静态方法
    static TimeZone utc();
    static TimeZone systemTimeZone();
    static TimeZone fromOffset(int offsetSeconds);

    // 属性访问
    bool isValid() const { return valid_; }
    std::string name() const { return id_; }
    int offsetFromUtc() const { return offset_; }
    bool hasDaylightTime() const { return hasDaylightTime_; }
    bool isDaylightTime(const class DateTime& dt) const;

    // 静态方法
    static std::vector<TimeZone> availableTimeZones();

    // 比较操作符
    bool operator==(const TimeZone& other) const {
        return offset_ == other.offset_ && id_ == other.id_;
    }

private:
    TimeZone(const std::string& id, int offset, bool hasDaylightTime = false);

    std::string id_;            // 时区ID
    int offset_;                // UTC偏移（秒）
    bool hasDaylightTime_;      // 是否支持夏令时
    bool valid_;                // 是否有效
};

// 日期时间类
class DateTime {
public:
    // 构造函数
    DateTime();
    DateTime(const Date& date, const Time& time);
    DateTime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int msec = 0);
    DateTime(time_t timestamp);
    DateTime(const struct tm& tm);

    // 属性访问
    Date date() const { return date_; }
    Time time() const { return time_; }
    TimeZone timeZone() const { return timeZone_; }
    int year() const { return date_.year(); }
    int month() const { return date_.month(); }
    int day() const { return date_.day(); }
    int hour() const { return time_.hour(); }
    int minute() const { return time_.minute(); }
    int second() const { return time_.second(); }
    int msec() const { return time_.msec(); }
    int dayOfWeek() const { return date_.dayOfWeek(); }
    int dayOfYear() const { return date_.dayOfYear(); }
    int daysInMonth() const { return date_.daysInMonth(); }

    // 验证
    bool isValid() const { return date_.isValid() && time_.isValid() && timeZone_.isValid(); }
    bool isNull() const { return !isValid(); }
    bool isDaylightTime() const { return timeZone_.isDaylightTime(*this); }

    // 计算操作
    DateTime addYears(int years) const;
    DateTime addMonths(int months) const;
    DateTime addDays(int days) const;
    DateTime addHours(int hours) const;
    DateTime addMinutes(int minutes) const;
    DateTime addSecs(int seconds) const;
    DateTime addMSecs(int msecs) const;

    // 时间差
    int64_t daysTo(const DateTime& other) const;
    int64_t secsTo(const DateTime& other) const;
    int64_t msecsTo(const DateTime& other) const;

    // 转换方法
    DateTime toTimeZone(const TimeZone& zone) const;
    DateTime toUTC() const;
    DateTime toLocalTime() const;
    time_t toTime_t() const;
    int64_t toMSecsSinceEpoch() const;
    std::string toString(const std::string& format = "YYYY-MM-DD HH:MM:SS") const;
    std::string toISOString() const;

    // 静态方法
    static DateTime currentDateTime();
    static DateTime fromMSecsSinceEpoch(int64_t msecs, const TimeZone& zone = TimeZone::utc());
    static DateTime fromString(const std::string& str, DateFormat format = DateFormat::ISODate);

    // 操作符重载
    bool operator==(const DateTime& other) const;
    bool operator!=(const DateTime& other) const;
    bool operator<(const DateTime& other) const;
    bool operator<=(const DateTime& other) const;
    bool operator>(const DateTime& other) const;
    bool operator>=(const DateTime& other) const;

private:
    // 内部方法
    void initFromTimestamp(int64_t msecs, const TimeZone& zone);
    struct tm toTM() const;

    Date date_;
    Time time_;
    TimeZone timeZone_;
};

// 日期时间工具类
class DateTimeUtils {
public:
    static int weekNumber(int year, int month, int day);
    static bool isValidDate(int year, int month, int day);
    static bool isValidTime(int hour, int minute, int second, int msec = 0);
    static int daysInMonth(int year, int month);
    static bool isLeapYear(int year);
};

// 频率控制类
class Rate {
public:
    explicit Rate(float frequency = 1.0f);
    void reset(float frequency = -1.0f);
    bool sleep();
    bool wakeup(float sigma = 0.0f);

private:
    DateTime startTime_;
    std::chrono::microseconds interval_;
};

} // namespace cytoolkit

#endif // MODERN_DATETIME_H